home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / monmove.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  31.4 KB  |  1,142 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)monmove.c    3.1    93/05/15    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "mfndpos.h"
  7. #include "artifact.h"
  8.  
  9. #ifdef OVL0
  10.  
  11. static int FDECL(disturb,(struct monst *));
  12. static void FDECL(distfleeck,(struct monst *,int *,int *,int *));
  13. STATIC_DCL boolean FDECL(mdig_tunnel,(struct monst *));
  14. static void FDECL(watch_on_duty,(struct monst *));
  15.  
  16. #endif /* OVL0 */
  17. #ifdef OVLB
  18.  
  19. boolean /* TRUE : mtmp died */
  20. mb_trapped(mtmp)
  21. register struct monst *mtmp;
  22. {
  23.     if (flags.verbose) {
  24.         if (cansee(mtmp->mx, mtmp->my))
  25.            pline("KABOOM!!  You see a door explode.");
  26.         else if (flags.soundok)
  27.                You("hear a distant explosion.");
  28.     }
  29.     mtmp->mstun = 1;
  30.     mtmp->mhp -= rnd(15);
  31.     if(mtmp->mhp <= 0) {
  32.         mondied(mtmp);
  33. #ifdef MUSE
  34.         if (mtmp->mhp > 0) /* lifesaved */
  35.             return(FALSE);
  36.         else
  37. #endif
  38.             return(TRUE);
  39.     }
  40.     return(FALSE);
  41. }
  42.  
  43. #endif /* OVLB */
  44. #ifdef OVL0
  45.  
  46. static void
  47. watch_on_duty(mtmp)
  48. register struct monst *mtmp;
  49. {
  50.     register s_level *slev = Is_special(&u.uz);
  51.     int    x, y;
  52.  
  53.     if(slev && slev->flags.town && mtmp->mpeaceful &&
  54.        m_canseeu(mtmp) && !rn2(3)) {
  55.  
  56.         if(picking_lock(&x, &y) && IS_DOOR(levl[x][y].typ) &&
  57.            (levl[x][y].doormask & D_LOCKED)) {
  58.  
  59.         if(couldsee(mtmp->mx, mtmp->my)) {
  60.  
  61.           pline("%s yells:", Amonnam(mtmp));
  62.           if(levl[x][y].looted & D_WARNED) {
  63.             verbalize("Halt, thief!  You're under arrest!");
  64.             (void) angry_guards(!(flags.soundok));
  65.           } else {
  66.             verbalize("Hey, stop picking that lock!");
  67.             levl[x][y].looted |=  D_WARNED;
  68.           }
  69.           stop_occupation();
  70.         }
  71.         }
  72.     }
  73. }
  74.  
  75. /* Return TRUE if monster died, FALSE otherwise. */
  76. STATIC_OVL boolean
  77. mdig_tunnel(mtmp)
  78. register struct monst *mtmp;
  79. {
  80.     register struct rm *here;
  81.     register int pile;
  82.  
  83.     here = &levl[mtmp->mx][mtmp->my];
  84.     if (here->typ == SDOOR) here->typ = DOOR;
  85.  
  86.     /* Eats away door if present & closed or locked */
  87.     if(closed_door(mtmp->mx, mtmp->my)) {
  88.         if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
  89.         add_damage(mtmp->mx, mtmp->my, 0L);
  90.         unblock_point(mtmp->mx,mtmp->my);    /* vision */
  91.         if(here->doormask & D_TRAPPED) {
  92.         here->doormask = D_NODOOR;
  93.         if(mb_trapped(mtmp)) {    /* mtmp is killed */
  94.             newsym(mtmp->mx,mtmp->my);
  95.             return TRUE;
  96.         }
  97.         } else {
  98.         if(!rn2(3) && flags.verbose)    /* not too often.. */
  99.             You("feel an unexpected draft.");
  100.         here->doormask = D_BROKEN;
  101.         }
  102.         newsym(mtmp->mx,mtmp->my);
  103.         return FALSE;
  104.     } else
  105.     if (!IS_ROCK(here->typ)) /* no dig */
  106.         return(FALSE);
  107.  
  108.     /* Only rock and walls fall through to this point. */
  109.     if ((here->diggable & W_NONDIGGABLE)) {
  110.         impossible("mdig_tunnel:  %s at (%d,%d) is undiggable",
  111.                (IS_WALL(here->typ) ? "wall" : "stone"),
  112.                (int) mtmp->mx, (int) mtmp->my);
  113.         return FALSE;    /* still alive */
  114.     }
  115.  
  116.     if(IS_WALL(here->typ)) {
  117.         if(flags.soundok && flags.verbose && !rn2(5))
  118.         You("hear crashing rock.");
  119.         if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
  120.             add_damage(mtmp->mx, mtmp->my, 0L);
  121.         if (level.flags.is_maze_lev) {
  122.         here->typ = ROOM;
  123.         } else if (level.flags.is_cavernous_lev) {
  124.         here->typ = CORR;
  125.         } else {
  126.         here->typ = DOOR;
  127.         here->doormask = D_NODOOR;
  128.         }
  129.     } else    
  130.         here->typ = CORR;
  131.  
  132.     pile = rnd(12);
  133.     if(pile < 5)    /* leave behind some rocks? */
  134.         (void) mksobj_at((pile == 1)? BOULDER : ROCK, 
  135.                  mtmp->mx, mtmp->my, TRUE);
  136.     newsym(mtmp->mx,mtmp->my);
  137.     if(sobj_at(BOULDER, mtmp->mx, mtmp->my) == (struct obj *)0)
  138.         unblock_point(mtmp->mx,mtmp->my);    /* vision */
  139.     return FALSE ;
  140. }
  141.  
  142. #endif /* OVL0 */
  143. #ifdef OVL1
  144.  
  145. int
  146. dochugw(mtmp)
  147.     register struct monst *mtmp;
  148. {
  149.     register int x = mtmp->mx;
  150.     register int y = mtmp->my;
  151.     register int rd = dochug(mtmp);
  152.     register int dd;
  153.  
  154.     if(Warning && !rd && !mtmp->mpeaceful &&
  155.             (dd = distu(mtmp->mx,mtmp->my)) < distu(x,y) &&
  156.             dd < 100 && !canseemon(mtmp)) {
  157.         /* Note: this assumes we only want to warn against the monster to
  158.          * which the weapon does extra damage, as there is no "monster
  159.          * which the weapon warns against" field.
  160.          */
  161.         if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1))
  162.         warnlevel = 100;
  163.         else if ((int) (mtmp->m_lev / 4) > warnlevel)
  164.         warnlevel = (mtmp->m_lev / 4);
  165.     }
  166.     /* check whether hero notices monster and stops current activity */
  167.     if (occupation && !rd && !Confusion &&
  168.         (!mtmp->mpeaceful || Hallucination) &&
  169.         canseemon(mtmp) && !cansee(x,y) &&
  170.         distu(mtmp->mx,mtmp->my) <= (BOLT_LIM+1)*(BOLT_LIM+1))
  171.         stop_occupation();
  172.  
  173.     return(rd);
  174. }
  175.  
  176. #endif /* OVL1 */
  177. #ifdef OVL2
  178.  
  179. boolean
  180. onscary(x, y, mtmp)
  181. int x, y;
  182. struct monst *mtmp;
  183. {
  184.     if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
  185.             is_lminion(mtmp->data) || is_rider(mtmp->data) ||
  186.             mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful ||
  187.             mtmp->data == &mons[PM_MINOTAUR])
  188.         return(FALSE);
  189.     return((boolean)(
  190. #ifdef ELBERETH
  191.            sengr_at("Elbereth", x, y) ||
  192. #endif
  193.             sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0));
  194. }
  195.  
  196. #endif /* OVL2 */
  197. #ifdef OVL0
  198.  
  199. /*
  200.  * Possibly awaken the given monster.  Return a 1 if the monster has been
  201.  * jolted awake.
  202.  */
  203. static int
  204. disturb(mtmp)
  205.     register struct monst *mtmp;
  206. {
  207.     /*
  208.      * + Ettins are hard to surprise.
  209.      * + Nymphs, jabberwocks, and leprechauns do not easily wake up.
  210.      *
  211.      * Wake up if:
  212.      *    in direct LOS                        AND
  213.      *    within 10 squares                    AND
  214.      *    not stealthy or (mon is an ettin and 9/10)        AND
  215.      *    (mon is not a nymph, jabberwock, or leprechaun) or 1/50    AND
  216.      *    Aggravate or mon is (dog or human) or
  217.      *        (1/7 and mon is not mimicing furniture or object)
  218.      */
  219.     if(couldsee(mtmp->mx,mtmp->my) &&
  220.         distu(mtmp->mx,mtmp->my) <= 100 &&
  221.         (!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) &&
  222.         (!(mtmp->data->mlet == S_NYMPH
  223.             || mtmp->data == &mons[PM_JABBERWOCK]
  224.             || mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) &&
  225.         (Aggravate_monster
  226.             || (mtmp->data->mlet == S_DOG ||
  227.                 mtmp->data->mlet == S_HUMAN)
  228.             || (!rn2(7) && mtmp->m_ap_type != M_AP_FURNITURE &&
  229.                 mtmp->m_ap_type != M_AP_OBJECT) )) {
  230.  
  231.         mtmp->msleep = 0;
  232.         return(1);
  233.     }
  234.     return(0);
  235. }
  236.  
  237. static void
  238. distfleeck(mtmp,inrange,nearby,scared)
  239. register struct monst *mtmp;
  240. int *inrange, *nearby, *scared;
  241. {
  242.     int seescaryx, seescaryy;
  243.  
  244.     *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=
  245.                             (BOLT_LIM * BOLT_LIM));
  246.     *nearby = *inrange && monnear(mtmp, mtmp->mux, mtmp->muy);
  247.  
  248.     /* Note: if your image is displaced, the monster sees the Elbereth
  249.      * at your displaced position, thus never attacking your displaced
  250.      * position, but possibly attacking you by accident.  If you are
  251.      * invisible, it sees the Elbereth at your real position, thus never
  252.      * running into you by accident but possibly attacking the spot
  253.      * where it guesses you are.
  254.      */
  255.     if (Invis && !perceives(mtmp->data)) {
  256.         seescaryx = mtmp->mux;
  257.         seescaryy = mtmp->muy;
  258.     } else {
  259.         seescaryx = u.ux;
  260.         seescaryy = u.uy;
  261.     }
  262.     *scared = (*nearby && (onscary(seescaryx, seescaryy, mtmp) ||
  263.                    (!mtmp->mpeaceful &&
  264.                     in_your_sanctuary(mtmp->mx, mtmp->my))));
  265.  
  266.     if(*scared && !mtmp->mflee) {
  267. #ifdef POLYSELF
  268.         if (!sticks(uasmon))
  269. #endif
  270.             unstuck(mtmp);    /* monster lets go when fleeing */
  271.         mtmp->mflee = 1;
  272. #ifdef STUPID
  273.         if (rn2(7))
  274.             mtmp->mfleetim = rnd(10);
  275.         else
  276.             mtmp->mfleetim = rnd(100);
  277. #else
  278.         mtmp->mfleetim = rnd(rn2(7) ? 10 : 100);
  279. #endif
  280.     }
  281.  
  282. }
  283.  
  284. /* returns 1 if monster died moving, 0 otherwise */
  285. /* The whole dochugw/m_move/distfleeck/mfndpos section is serious spaghetti
  286.  * code. --KAA
  287.  */
  288. int
  289. dochug(mtmp)
  290. register struct monst *mtmp;
  291. {
  292.     register struct permonst *mdat = mtmp->data;
  293.     register int tmp=0;
  294.     int inrange, nearby, scared;
  295.  
  296. /*    Pre-movement adjustments    */
  297.  
  298.     if(mtmp->cham && !rn2(6))    /* polymorph chameleons */
  299.         (void) newcham(mtmp, (struct permonst *)0);
  300.  
  301.     /* regenerate monsters */
  302.     if (mtmp->mhp < mtmp->mhpmax && (!(moves%20) || regenerates(mdat)))
  303.         mtmp->mhp++;
  304.     if(mtmp->mspec_used) mtmp->mspec_used--;
  305.  
  306.     /* polymorph lycanthropes */
  307.     were_change(mtmp);
  308.  
  309.     /* check for waitmask status change */
  310.     if((mtmp->data->mflags3 & M3_WAITFORU) &&
  311.        (m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax))
  312.         mtmp->data->mflags3 &= ~M3_WAITFORU;
  313.  
  314. #ifdef MULDGN
  315.     /* update quest status flags */
  316.     quest_stat_check(mtmp);
  317. #endif
  318.  
  319.     if(!mtmp->mcanmove || (mtmp->data->mflags3 & M3_WAITMASK)) {
  320.         if (Hallucination) newsym(mtmp->mx,mtmp->my);
  321. #ifdef MULDGN
  322.         if(mtmp->mcanmove && (mtmp->data->mflags3 & M3_CLOSE) &&
  323.            !mtmp->msleep && monnear(mtmp, u.ux, u.uy))
  324.         quest_talk(mtmp);    /* give the leaders a chance to speak */
  325. #endif
  326.         return(0);    /* other frozen monsters can't do anything */
  327.     }
  328.  
  329.     /* there is a chance we will wake it */
  330.     if(mtmp->msleep && !disturb(mtmp)) {
  331.         if (Hallucination) newsym(mtmp->mx,mtmp->my);
  332.         return(0);
  333.     }
  334.  
  335.     /* not frozen or sleeping: wipe out texts written in the dust */
  336.     wipe_engr_at(mtmp->mx, mtmp->my, 1);
  337.  
  338.     /* confused monsters get unconfused with small probability */
  339.     if (mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
  340.  
  341.     /* stunned monsters get un-stunned with larger probability */
  342.     if (mtmp->mstun && !rn2(10)) mtmp->mstun = 0;
  343.  
  344.     /* some monsters teleport */
  345.     if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) {
  346.         rloc(mtmp);
  347.         return(0);
  348.     }
  349.     if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
  350.         m_respond(mtmp);
  351.     if (mdat == &mons[PM_MEDUSA] && cansee(mtmp->mx, mtmp->my))
  352.         m_respond(mtmp);
  353.     if (mdat->mmove < rnd(6)) return(0);
  354.  
  355.     /* fleeing monsters might regain courage */
  356.     if (mtmp->mflee && !mtmp->mfleetim
  357.        && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0;
  358.  
  359.     set_apparxy(mtmp);
  360.     /* Must be done after you move and before the monster does.  The
  361.      * set_apparxy() call in m_move() doesn't suffice since the variables
  362.      * inrange, etc. all depend on stuff set by set_apparxy().
  363.      */
  364.  
  365.     /* Monsters that want to acquire things */
  366.     /* may teleport, so do it before inrange is set */
  367.     if(is_covetous(mtmp->data)) (void) tactics(mtmp);
  368.  
  369.     /* check distance and scariness of attacks */
  370.     distfleeck(mtmp,&inrange,&nearby,&scared);
  371.  
  372. #ifdef MUSE
  373.     if(find_defensive(mtmp)) {
  374.         if (use_defensive(mtmp) != 0)
  375.             return 1;
  376.     } else if(find_misc(mtmp)) {
  377.         if (use_misc(mtmp) != 0)
  378.             return 1;
  379.     }
  380. #endif
  381.  
  382.     /* Demonic Blackmail! */
  383.     if(nearby && mdat->msound == MS_BRIBE &&
  384.        mtmp->mpeaceful && !mtmp->mtame) {
  385.         if (mtmp->mux != u.ux || mtmp->muy != u.uy) {
  386.             pline("%s whispers at thin air.",
  387.                 cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It");
  388. #ifdef POLYSELF
  389.             if (is_demon(uasmon)) rloc(mtmp);
  390.               /* "Good hunting, brother" */
  391.             else {
  392. #endif
  393.                 mtmp->minvis = 0;
  394.                 /* Why?  For the same reason in real demon talk */
  395.                 pline("%s gets angry!", Amonnam(mtmp));
  396.                 mtmp->mpeaceful = 0;
  397.                 /* since no way is an image going to pay it off */
  398. #ifdef POLYSELF
  399.             }
  400. #endif
  401.         } else if(demon_talk(mtmp)) return(1);    /* you paid it off */
  402.     }
  403.  
  404.     /* the watch will look around and see if you are up to no good :-) */
  405.     if (mdat == &mons[PM_WATCHMAN] || mdat == &mons[PM_WATCH_CAPTAIN]) 
  406.         watch_on_duty(mtmp);
  407.  
  408.     else if (mdat == &mons[PM_MIND_FLAYER] && !rn2(20)) {
  409.         struct monst *m2, *nmon = (struct monst *)0;
  410.  
  411.         if (canseemon(mtmp))
  412.             pline("%s concentrates.", Monnam(mtmp));
  413.         if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) {
  414.             You("sense a faint wave of psychic energy.");
  415.             goto toofar;
  416.         }
  417.         pline("A wave of psychic energy pours over you!");
  418.         if (mtmp->mpeaceful &&
  419.             (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
  420.             pline("It feels quite soothing.");
  421.         else {
  422.             register boolean m_sen = sensemon(mtmp);
  423.  
  424.             if (m_sen || (Telepat && rn2(2)) || !rn2(10)) {
  425.                 int dmg;
  426.                 pline("It locks on to your %s!",
  427.                     m_sen ? "telepathy" :
  428.                     Telepat ? "latent telepathy" : "mind");
  429.                 dmg = rnd(15);
  430.                 if (Half_spell_damage) dmg = (dmg+1) / 2;
  431.                 losehp(dmg, "psychic blast", KILLED_BY_AN);
  432.             }
  433.         }
  434.         for(m2=fmon; m2; m2 = nmon) {
  435.             nmon = m2->nmon;
  436.             if (m2->mpeaceful != mtmp->mpeaceful) continue;
  437.             if (mindless(m2->data)) continue;
  438.             if (m2 == mtmp) continue;
  439.             if ((telepathic(m2->data) &&
  440.                 (rn2(2) || m2->mblinded)) || !rn2(10)) {
  441.                 if (cansee(m2->mx, m2->my))
  442.                     pline("It locks on to %s.", mon_nam(m2));
  443.                 m2->mhp -= rnd(15);
  444.                 if (m2->mhp <= 0)
  445.                     monkilled(m2, "", AD_DRIN);
  446.             }
  447.         }
  448.     }
  449. toofar:
  450. #ifdef MUSE
  451.     /* If monster is nearby you, and has to wield a weapon, do so.   This
  452.      * costs the monster a move, of course.
  453.      */
  454.     if((!mtmp->mpeaceful || Conflict) && inrange &&
  455.        dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= 8
  456.        && attacktype(mdat, AT_WEAP)) {
  457.         if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
  458.         mtmp->weapon_check = NEED_HTH_WEAPON;
  459.         if (mon_wield_item(mtmp) != 0) return(0);
  460.         }
  461.     }
  462. #endif
  463. /*    Now the actual movement phase    */
  464.  
  465.     if(!nearby || mtmp->mflee || scared ||
  466.        mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||
  467.        (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
  468.        (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
  469.        (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
  470.  
  471.         tmp = m_move(mtmp, 0);
  472.         distfleeck(mtmp,&inrange,&nearby,&scared);    /* recalc */
  473.  
  474.         switch (tmp) {
  475.  
  476.             case 0:    /* no movement, but it can still attack you */
  477.             case 3:    /* absolutely no movement */
  478.                 /* for pets, case 0 and 3 are equivalent */
  479.              /* During hallucination, monster appearance should
  480.               * still change - even if it doesn't move.
  481.                */
  482.              if(Hallucination) newsym(mtmp->mx,mtmp->my);
  483.              break;
  484.              case 1:    /* monster moved */
  485.             /* Maybe it stepped on a trap and fell asleep... */
  486.             if(mtmp->msleep || !mtmp->mcanmove) return(0);
  487.              if(!nearby && ranged_attk(mdat)) break;
  488.              else if(mdat->mmove <= 12) {
  489.                 /* a monster that's digesting you can move at the
  490.                  * same time -dlc
  491.                  */
  492.                 if(u.uswallow && mtmp == u.ustuck)
  493.                 return(mattacku(mtmp));
  494.                 return(0);
  495.             }
  496.              break;
  497.              case 2:    /* monster died */
  498.              return(1);
  499.          }
  500.     }
  501.  
  502. /*    Now, attack the player if possible - one attack set per monst    */
  503.  
  504.     if (!mtmp->mpeaceful ||
  505.         (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) {
  506.         if(inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3)
  507.         if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
  508.  
  509.         if(mtmp->wormno) wormhitu(mtmp);
  510.     }
  511. #ifdef MULDGN
  512.     /* special speeches for quest monsters */
  513.     if(!mtmp->msleep && mtmp->mcanmove && nearby)
  514.         quest_talk(mtmp);
  515.     else
  516. #endif
  517.         /* extra emotional attack for vile monsters */
  518.         if(inrange && mtmp->data->msound == MS_CUSS && !mtmp->mpeaceful &&
  519.            couldsee(mtmp->mx, mtmp->my) && !mtmp->minvis && !rn2(5))
  520.         cuss(mtmp);
  521.  
  522.     /* extra movement for fast monsters */
  523.     if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1);
  524.     return(tmp == 2);
  525. }
  526.  
  527. static NEARDATA const char practical[] = { WEAPON_CLASS, ARMOR_CLASS, GEM_CLASS, FOOD_CLASS, 0 };
  528. static NEARDATA const char magical[] = {
  529.     AMULET_CLASS, POTION_CLASS, SCROLL_CLASS, WAND_CLASS, RING_CLASS,
  530.     SPBOOK_CLASS, 0 };
  531. static NEARDATA const char indigestion[] = { BALL_CLASS, ROCK_CLASS, 0 };
  532.  
  533. #ifdef POLYSELF
  534. boolean
  535. itsstuck(mtmp)
  536. register struct monst *mtmp;
  537. {
  538.     if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) {
  539.         pline("%s cannot escape from you!", Monnam(mtmp));
  540.         return(TRUE);
  541.     }
  542.     return(FALSE);
  543. }
  544. #endif
  545.  
  546. int
  547. m_move(mtmp, after)
  548. register struct monst *mtmp;
  549. register int after;
  550. {
  551.     register int appr;
  552.     xchar gx,gy,nix,niy,chcnt;
  553.     int chi;    /* could be schar except for stupid Sun-2 compiler */
  554.     boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
  555.     boolean likerock=0, can_tunnel=0;
  556.     boolean can_open=0, can_unlock=0, doorbuster=0;
  557. #ifdef MUSE
  558.     boolean uses_items=0;
  559. #endif
  560.     struct permonst *ptr;
  561.     schar mmoved = 0;    /* not strictly nec.: chi >= 0 will do */
  562.     long info[9];
  563.     long flag;
  564.     int  omx = mtmp->mx, omy = mtmp->my;
  565. #ifdef MUSE
  566.     struct obj *mw_tmp;
  567. #endif
  568.  
  569.     if(mtmp->mtrapped) {
  570.         int i = mintrap(mtmp);
  571.         if(i >= 2) { newsym(mtmp->mx,mtmp->my); return(2); }/* it died */
  572.         if(i == 1) return(0);    /* still in trap, so didn't move */
  573.     }
  574.     ptr = mtmp->data; /* mintrap() can change mtmp->data -dlc */
  575.     if(hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10))
  576.         return(0);        /* do not leave hiding place */
  577.     if(mtmp->meating) {
  578.         mtmp->meating--;
  579.         return(3);            /* still eating */
  580.     }
  581.  
  582.     set_apparxy(mtmp);
  583.     /* where does mtmp think you are? */
  584.     /* Not necessary if m_move called from this file, but necessary in
  585.      * other calls of m_move (ex. leprechauns dodging)
  586.      */
  587.     can_tunnel = tunnels(ptr) &&
  588. #ifdef REINCARNATION
  589.         !Is_rogue_level(&u.uz) &&
  590. #endif
  591. #ifdef MUSE
  592.         (!needspick(ptr) ||
  593.          (m_carrying(mtmp, PICK_AXE) &&
  594.           (mtmp->weapon_check != NO_WEAPON_WANTED ||
  595.            !(mw_tmp = MON_WEP(mtmp)) || mw_tmp->otyp == PICK_AXE)));
  596. #else
  597.         (!needspick(ptr) || m_carrying(mtmp, PICK_AXE));
  598. #endif
  599.     can_open = !(nohands(ptr) || verysmall(ptr));
  600.     can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) || mtmp->iswiz);
  601.     doorbuster = is_giant(ptr);
  602.     if(mtmp->wormno) goto not_special;
  603.     /* my dog gets special treatment */
  604.     if(mtmp->mtame) {
  605.         mmoved = dog_move(mtmp, after);
  606.         goto postmov;
  607.     }
  608.  
  609.     /* likewise for shopkeeper */
  610.     if(mtmp->isshk) {
  611.         mmoved = shk_move(mtmp);
  612.         if(mmoved == -2) return(2);
  613.         if(mmoved >= 0) goto postmov;
  614.         mmoved = 0;        /* follow player outside shop */
  615.     }
  616.  
  617.     /* and for the guard */
  618.     if(mtmp->isgd) {
  619.         mmoved = gd_move(mtmp);
  620.         if(mmoved == -2) return(2);
  621.         if(mmoved >= 0) goto postmov;
  622.         mmoved = 0;
  623.     }
  624.  
  625.     /* and the acquisitive monsters get special treatment */
  626.     if(is_covetous(ptr)) {
  627.         xchar tx = (xchar)((mtmp->mstrategy >> 16) & 0xff),
  628.           ty = (xchar)((mtmp->mstrategy >> 8) & 0xff);
  629.         struct monst *intruder = m_at(tx, ty);
  630.         /*
  631.          * if there's a monster on the object or in possesion of it,
  632.          * attack it.
  633.          */
  634.         if((dist2(mtmp->mx, mtmp->my, tx, ty) < 2) &&
  635.            intruder && (intruder != mtmp)) {
  636.  
  637.         if(mattackm(mtmp, intruder) == 2) return(2);
  638.         mmoved = 1;
  639.         } else mmoved = 0;
  640.         goto postmov;
  641.     }
  642.  
  643.     /* and for the priest */
  644.     if(mtmp->ispriest) {
  645.         mmoved = pri_move(mtmp);
  646.         if(mmoved == -2) return(2);
  647.         if(mmoved >= 0) goto postmov;
  648.         mmoved = 0;
  649.     }
  650.  
  651. #ifdef MAIL
  652.     if(ptr == &mons[PM_MAIL_DAEMON]) {
  653.         if(flags.soundok && canseemon(mtmp))
  654.         verbalize("I'm late!");
  655.         mongone(mtmp);
  656.         return(2);        
  657.     }
  658. #endif
  659.  
  660.     /* teleport if that lies in our nature */
  661.     if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan) {
  662.         if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
  663.         rloc(mtmp);
  664.         else
  665.         mnexto(mtmp);
  666.         mmoved = 1;
  667.         goto postmov;
  668.     }
  669. not_special:
  670.     if(u.uswallow && !mtmp->mflee && u.ustuck != mtmp) return(1);
  671.     appr = 1;
  672.     omx = mtmp->mx;
  673.     omy = mtmp->my;
  674.     gx = mtmp->mux;
  675.     gy = mtmp->muy;
  676.     if(mtmp->mflee) appr = -1;
  677.     if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck))
  678.         appr = 0;
  679.     else {
  680.         boolean should_see = (couldsee(omx, omy) &&     
  681.                           (levl[gx][gy].lit || 
  682.                        !levl[omx][omy].lit) &&
  683.                       (dist2(omx, omy, gx, gy) <= 36));
  684.  
  685.         if (!mtmp->mcansee || 
  686.                 (should_see && Invis && !perceives(ptr)) || 
  687. #ifdef POLYSELF
  688.                 (u.usym == S_MIMIC_DEF) || u.uundetected ||
  689. #endif
  690.                 (mtmp->mpeaceful && !mtmp->isshk) ||  /* allow shks to follow */
  691.                 ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT ||
  692.               ptr->mlet == S_LIGHT) && !rn2(3)))
  693.             appr = 0;  
  694.     
  695.             if(monsndx(ptr) == PM_LEPRECHAUN && (appr == 1) && 
  696.                (mtmp->mgold > u.ugold))
  697.             appr = -1;
  698.  
  699.         if (!should_see && can_track(ptr)) {
  700.             register coord *cp;
  701.  
  702.             cp = gettrack(omx,omy);
  703.             if (cp) {
  704.                     gx = cp->x;
  705.                     gy = cp->y;
  706.             }
  707.         }
  708.     }
  709.  
  710. #ifdef REINCARNATION
  711.     if (!Is_rogue_level(&u.uz))
  712. #endif
  713.     {
  714.         register int pctload = (curr_mon_load(mtmp) * 100) /
  715.             max_mon_load(mtmp);
  716.  
  717.         /* look for gold or jewels nearby */
  718.         likegold = (likes_gold(ptr) && pctload < 95);
  719.         likegems = (likes_gems(ptr) && pctload < 85);
  720. #ifdef MUSE
  721.         uses_items = (!mindless(ptr) && !is_animal(ptr)
  722.             && pctload < 75);
  723. #endif
  724.         likeobjs = (likes_objs(ptr) && pctload < 75);
  725.         likemagic = (likes_magic(ptr) && pctload < 85);
  726.         likerock = (throws_rocks(ptr) && pctload < 50);
  727.         conceals = hides_under(ptr);
  728.     }
  729.  
  730. #define SQSRCHRADIUS    5
  731.  
  732.       { register int minr = SQSRCHRADIUS;    /* not too far away */
  733.     register struct obj *otmp;
  734.     register int xx, yy;
  735.     int oomx, oomy, lmx, lmy;
  736.  
  737.     /* cut down the search radius if it thinks character is closer. */
  738.     if(distmin(mtmp->mux, mtmp->muy, omx, omy) < SQSRCHRADIUS &&
  739.         !mtmp->mpeaceful) minr--;
  740.     /* guards shouldn't get too distracted */
  741.     if(!mtmp->mpeaceful && is_mercenary(ptr)) minr = 1;
  742.  
  743.     if((likegold || likegems || likeobjs || likemagic || likerock || conceals)
  744.           && (!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) {
  745.     look_for_obj:
  746.         oomx = min(COLNO-1, omx+minr);
  747.         oomy = min(ROWNO-1, omy+minr);
  748.         lmx = max(1, omx-minr);
  749.         lmy = max(0, omy-minr);
  750.         for(otmp = fobj; otmp; otmp = otmp->nobj) {
  751.         xx = otmp->ox;
  752.         yy = otmp->oy;
  753.         /* Nymphs take everything.  Most other creatures should not
  754.          * pick up corpses except as a special case like in
  755.          * searches_for_item().  We need to do this check in
  756.          * mpickstuff() as well.
  757.          */
  758.         if(xx >= lmx && xx <= oomx && yy >= lmy && yy <= oomy) {
  759.             if(((likegold && otmp->otyp == GOLD_PIECE) ||
  760.                (likeobjs && index(practical, otmp->oclass) &&
  761.             (otmp->otyp != CORPSE || ptr->mlet == S_NYMPH)) ||
  762.                (likemagic && index(magical, otmp->oclass)) ||
  763. #ifdef MUSE
  764.                (uses_items && searches_for_item(mtmp, otmp)) ||
  765. #endif
  766.                (likerock && otmp->otyp == BOULDER) ||
  767.                (likegems && otmp->oclass == GEM_CLASS &&
  768.             objects[otmp->otyp].oc_material != MINERAL) ||
  769.                (conceals && !cansee(otmp->ox,otmp->oy)) ||
  770.                (ptr == &mons[PM_GELATINOUS_CUBE] &&
  771.             !index(indigestion, otmp->oclass) &&
  772.             !(otmp->otyp == CORPSE &&
  773.               otmp->corpsenm == PM_COCKATRICE))
  774.               ) && touch_artifact(otmp,mtmp)) {
  775.             if(can_carry(mtmp,otmp) &&
  776.                (throws_rocks(ptr) ||
  777.                 !sobj_at(BOULDER,xx,yy)) &&
  778.                (ptr->mlet != S_UNICORN ||
  779.                 objects[otmp->otyp].oc_material == GEMSTONE)) {
  780.                 minr = distmin(omx,omy,xx,yy);
  781.                 oomx = min(COLNO-1, omx+minr);
  782.                 oomy = min(ROWNO-1, omy+minr);
  783.                 lmx = max(1, omx-minr);
  784.                 lmy = max(0, omy-minr);
  785.                 gx = otmp->ox;
  786.                 gy = otmp->oy;
  787.             }
  788.             }
  789.         }
  790.         }
  791.     } else if(likegold) {
  792.         /* don't try to pick up anything else, but use the same loop */
  793. #ifdef MUSE
  794.         uses_items =
  795. #endif
  796.         likegems = likeobjs = likemagic = likerock = conceals = 0;
  797.         goto look_for_obj;
  798.     }
  799.  
  800.     if(minr < SQSRCHRADIUS && appr == -1) {
  801.         if(distmin(omx,omy,mtmp->mux,mtmp->muy) <= 3) {
  802.         gx = mtmp->mux;
  803.         gy = mtmp->muy;
  804.         } else
  805.         appr = 1;
  806.     }
  807.       }
  808.     nix = omx;
  809.     niy = omy;
  810.     flag = ALLOW_TRAPS;
  811.     if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
  812.         flag |= (ALLOW_SANCT | ALLOW_SSM);
  813.     else flag |= ALLOW_U;
  814.     if (ptr->mlet == S_UNICORN) flag |= NOTONL;
  815.     if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
  816.     if (can_tunnel) flag |= ALLOW_DIG;
  817.     if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
  818.     if (is_undead(ptr)) flag |= NOGARLIC;
  819.     if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
  820.     if (can_open) flag |= OPENDOOR;
  821.     if (can_unlock) flag |= UNLOCKDOOR;
  822.     if (doorbuster) flag |= BUSTDOOR;
  823.     {
  824.         register int i, j, nx, ny, nearer;
  825.         int jcnt, cnt;
  826.         int ndist, nidist;
  827.         register coord *mtrk;
  828.         coord poss[9];
  829.  
  830.         cnt = mfndpos(mtmp, poss, info, flag);
  831.         chcnt = 0;
  832.         jcnt = min(MTSZ, cnt-1);
  833.         chi = -1;
  834.         nidist = dist2(nix,niy,gx,gy);
  835.         /* allow monsters be shortsighted on some levels for balance */
  836.         if(!mtmp->mpeaceful && level.flags.shortsighted &&
  837.            nidist > (couldsee(nix,niy) ? 144 : 36) && appr == 1) appr = 0;
  838.  
  839.         for(i=0; i < cnt; i++) {
  840.         nx = poss[i].x;
  841.         ny = poss[i].y;
  842.  
  843.         if (appr != 0) {
  844.             mtrk = &mtmp->mtrack[0];
  845.             for(j=0; j < jcnt; mtrk++, j++)
  846.             if(nx == mtrk->x && ny == mtrk->y)
  847.                 if(rn2(4*(cnt-j)))
  848.                 goto nxti;
  849.         }
  850.  
  851.         nearer = ((ndist = dist2(nx,ny,gx,gy)) < nidist);
  852.  
  853.         if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
  854.            (!appr && !rn2(++chcnt)) || !mmoved) {
  855.             nix = nx;
  856.             niy = ny;
  857.             nidist = ndist;
  858.             chi = i;
  859.             mmoved = 1;
  860.         }
  861.         nxti:    ;
  862.         }
  863.     }
  864.  
  865.     if(mmoved) {
  866.         register int j;
  867. #ifdef POLYSELF
  868.         if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp))
  869.         return(3);
  870. #endif
  871. #ifdef MUSE
  872.         if (mmoved==1 && can_tunnel && needspick(ptr) &&
  873.         (!(mw_tmp = MON_WEP(mtmp)) || mw_tmp->otyp != PICK_AXE)) {
  874.         mtmp->weapon_check = NEED_PICK_AXE;
  875.         (void)mon_wield_item(mtmp);
  876.         }
  877. #endif
  878.         /* If ALLOW_U is set, either it's trying to attack you, or it
  879.          * thinks it is.  In either case, attack this spot in preference to
  880.          * all others.
  881.          */
  882.         if(info[chi] & ALLOW_U) {
  883.         nix = mtmp->mux;
  884.         niy = mtmp->muy;
  885.         }
  886.         if (nix == u.ux && niy == u.uy) {
  887.         mtmp->mux = u.ux;
  888.         mtmp->muy = u.uy;
  889.         return(0);
  890.         }
  891.         /* The monster may attack another based on 1 of 2 conditions:
  892.          * 1 - It may be confused.
  893.          * 2 - It may mistake the monster for your (displaced) image.
  894.          * Pets get taken care of above and shouldn't reach this code.
  895.          * Conflict gets handled even farther away (movemon()).
  896.          */
  897.         if((info[chi] & ALLOW_M) ||
  898.            (nix == mtmp->mux && niy == mtmp->muy)) {
  899.         struct monst *mtmp2;
  900.         int mstatus;
  901.         mtmp2 = m_at(nix,niy);
  902.  
  903.         mstatus = mattackm(mtmp, mtmp2);
  904.  
  905.         if (mstatus & MM_AGR_DIED)        /* aggressor died */
  906.             return 2;
  907.  
  908.         if ((mstatus & MM_HIT) && !(mstatus & MM_DEF_DIED)  &&
  909.             rn2(4) && mtmp2->mlstmv != monstermoves) {
  910.             mstatus = mattackm(mtmp2, mtmp);    /* return attack */
  911.             if (mstatus & MM_DEF_DIED)
  912.             return 2;
  913.         }
  914.         return 3;
  915.         }
  916.  
  917.         remove_monster(omx, omy);
  918.         place_monster(mtmp, nix, niy);
  919.         for(j = MTSZ-1; j > 0; j--)
  920.         mtmp->mtrack[j] = mtmp->mtrack[j-1];
  921.         mtmp->mtrack[0].x = omx;
  922.         mtmp->mtrack[0].y = omy;
  923.         /* Place a segment at the old position. */
  924.         if (mtmp->wormno) worm_move(mtmp);
  925.     } else {
  926.         if(ptr->mlet == S_UNICORN && rn2(2)) {
  927.         rloc(mtmp);
  928.         return(1);
  929.         }
  930.         if(mtmp->wormno) worm_nomove(mtmp);
  931.     }
  932. postmov:
  933.     if(mmoved == 1) {
  934.         boolean canseeit = cansee(mtmp->mx, mtmp->my);
  935.         boolean abstain = (mtmp->mpeaceful && !mtmp->mtame);
  936.  
  937.         newsym(omx,omy);        /* update the old position */
  938.         if (mintrap(mtmp) >= 2) {
  939.         if(mtmp->mx) newsym(mtmp->mx,mtmp->my);
  940.         return(2);    /* it died */
  941.         }
  942.         ptr = mtmp->data;
  943.  
  944.         /* open a door, or crash through it, if you can */
  945.         if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
  946.             && !passes_walls(ptr) /* doesn't need to open doors */
  947.             && !can_tunnel /* taken care of below */
  948.           ) {
  949.         struct rm *here = &levl[mtmp->mx][mtmp->my];
  950.         boolean btrapped = (here->doormask & D_TRAPPED);
  951.  
  952.         if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
  953.             if (flags.verbose && canseeit)
  954.             pline("%s %ss under the door.", Monnam(mtmp),
  955.                   (ptr == &mons[PM_FOG_CLOUD] ||
  956.                    ptr == &mons[PM_YELLOW_LIGHT])
  957.                   ? "flow" : "ooze");
  958.         } else if(here->doormask & D_LOCKED && can_unlock) {
  959.             if(btrapped) {
  960.             here->doormask = D_NODOOR;
  961.             newsym(mtmp->mx, mtmp->my);
  962.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  963.             if(mb_trapped(mtmp)) return(2);
  964.             } else {
  965.             if (flags.verbose) {
  966.                 if (canseeit)
  967.                    You("see a door unlock and open.");
  968.                 else if (flags.soundok)
  969.                    You("hear a door unlock and open.");
  970.                 }
  971.                 here->doormask = D_ISOPEN;
  972.             /* newsym(mtmp->mx, mtmp->my); */
  973.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  974.             }
  975.         } else if (here->doormask == D_CLOSED && can_open) {
  976.             if(btrapped) {
  977.             here->doormask = D_NODOOR;
  978.             newsym(mtmp->mx, mtmp->my);
  979.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  980.             if(mb_trapped(mtmp)) return(2);
  981.             } else {
  982.                 if (flags.verbose) {
  983.                 if (canseeit)
  984.                      You("see a door open.");
  985.                 else if (flags.soundok)
  986.                      You("hear a door open.");
  987.                 }
  988.                 here->doormask = D_ISOPEN;
  989.             /* newsym(mtmp->mx, mtmp->my); */  /* done below */
  990.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  991.             }
  992.         } else if (here->doormask & (D_LOCKED|D_CLOSED)) {
  993.             /* mfndpos guarantees this must be a doorbuster */
  994.             if(btrapped) {
  995.             here->doormask = D_NODOOR;
  996.             newsym(mtmp->mx, mtmp->my);
  997.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  998.             if(mb_trapped(mtmp)) return(2);
  999.             } else {
  1000.                 if (flags.verbose) {
  1001.                 if (canseeit)
  1002.                     You("see a door crash open.");
  1003.                 else if (flags.soundok)
  1004.                     You("hear a door crash open.");
  1005.                 }
  1006.                 if (here->doormask & D_LOCKED && !rn2(2))
  1007.                     here->doormask = D_NODOOR;
  1008.                 else here->doormask = D_BROKEN;
  1009.             /* newsym(mtmp->mx, mtmp->my); */ /* done below */
  1010.             unblock_point(mtmp->mx,mtmp->my); /* vision */
  1011.             }
  1012.         }
  1013.         }
  1014.  
  1015.         /* possibly dig */
  1016.         if (can_tunnel && mdig_tunnel(mtmp))
  1017.             return(2);    /* mon died (position already updated) */
  1018.  
  1019.         /* set also in domove(), hack.c */
  1020.         if (u.uswallow && mtmp == u.ustuck &&
  1021.                     (mtmp->mx != omx || mtmp->my != omy)) {
  1022.         /* If the monster moved, then update */
  1023.         u.ux0 = u.ux;
  1024.         u.uy0 = u.uy;
  1025.         u.ux = mtmp->mx;
  1026.         u.uy = mtmp->my;
  1027.         swallowed(0);
  1028.         } else
  1029.         newsym(mtmp->mx,mtmp->my);
  1030.  
  1031.         if(OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
  1032.         /* Maybe a rock mole just ate some metal object */
  1033.         if(metallivorous(ptr)) meatgold(mtmp);
  1034.  
  1035.         if(g_at(mtmp->mx,mtmp->my) && likegold &&
  1036.                     (!abstain || !rn2(10))) mpickgold(mtmp);
  1037.  
  1038.         /* Maybe a cube ate just about anything */
  1039.         if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp);
  1040.  
  1041.         if((!abstain || !rn2(10)) && 
  1042.            (!*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || !rn2(25))) {
  1043.             if(likeobjs) mpickstuff(mtmp, practical);
  1044.             if(likemagic) mpickstuff(mtmp, magical);
  1045.             if(likerock || likegems) mpickgems(mtmp);
  1046. #ifdef MUSE
  1047.             if(uses_items) mpickstuff(mtmp, (char *)0);
  1048. #endif
  1049.         }
  1050.  
  1051.         if(mtmp->minvis) {
  1052.             newsym(mtmp->mx, mtmp->my);
  1053.             if (mtmp->wormno) see_wsegs(mtmp);
  1054.         }
  1055.         }
  1056.  
  1057.         if(hides_under(ptr)) {
  1058.         mtmp->mundetected = OBJ_AT(mtmp->mx, mtmp->my);
  1059.         newsym(mtmp->mx, mtmp->my);
  1060.         }
  1061.     }
  1062.     return(mmoved);
  1063. }
  1064.  
  1065. #endif /* OVL0 */
  1066. #ifdef OVL2
  1067.  
  1068. boolean
  1069. closed_door(x, y)
  1070. register int x, y;
  1071. {
  1072.     return((boolean)(IS_DOOR(levl[x][y].typ) &&
  1073.             (levl[x][y].doormask & (D_LOCKED | D_CLOSED))));
  1074. }
  1075.  
  1076. boolean
  1077. accessible(x, y)
  1078. register int x, y;
  1079. {
  1080.     return((boolean)(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y)));
  1081. }
  1082.  
  1083. #endif /* OVL2 */
  1084. #ifdef OVL0
  1085.  
  1086. /* decide where the monster thinks you are standing */
  1087. void
  1088. set_apparxy(mtmp)
  1089. register struct monst *mtmp;
  1090. {
  1091.     boolean notseen, gotu;
  1092.     register int disp, mx = mtmp->mux, my = mtmp->muy;
  1093.  
  1094.     /*
  1095.      * do cheapest and/or most likely tests first
  1096.      */
  1097.  
  1098.     /* pet knows your smell; grabber still has hold of you */
  1099.     if (mtmp->mtame || mtmp == u.ustuck) goto found_you;
  1100.  
  1101.     /* monsters which know where you are don't suddenly forget,
  1102.        if you haven't moved away */
  1103.     if (mx == u.ux && my == u.uy) goto found_you;
  1104.  
  1105.     notseen = Invis && !perceives(mtmp->data);
  1106.     /* add cases as required.  eg. Displacement ... */
  1107.     disp = (notseen || Underwater ? 1 : Displaced ? 2 : 0);
  1108.     if (!disp) goto found_you;
  1109.  
  1110.     /* without something like the following, invis. and displ.
  1111.        are too powerful */
  1112.     gotu = notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE;
  1113.  
  1114.     /* If invis but not displaced, staying around gets you 'discovered' */
  1115.     gotu |= (!Displaced && u.dx == 0 && u.dy == 0);
  1116.  
  1117.     if (!gotu) {
  1118.         register int try_cnt = 0;
  1119.         do {
  1120.         if (++try_cnt > 200) goto found_you;        /* punt */
  1121.         mx = u.ux - disp + rn2(2*disp+1);
  1122.         my = u.uy - disp + rn2(2*disp+1);
  1123.         } while (!isok(mx,my)
  1124.           || (disp != 2 && mx == mtmp->mx && my == mtmp->my)
  1125.           || ((mx != u.ux || my != u.uy) &&
  1126.               !passes_walls(mtmp->data) &&
  1127.               (!ACCESSIBLE(levl[mx][my].typ) ||
  1128.             (closed_door(mx, my) && !amorphous(mtmp->data)))));
  1129.     } else {
  1130. found_you:
  1131.         mx = u.ux;
  1132.         my = u.uy;
  1133.     }
  1134.  
  1135.     mtmp->mux = mx;
  1136.     mtmp->muy = my;
  1137. }
  1138.  
  1139. #endif /* OVL0 */
  1140.  
  1141. /*monmove.c*/
  1142.